/**
 *
 * RIP - Routing Information Protocol > baseado na implementação de Kurose-Ross
 *
 * Laboratório de Redes de Computadores Bacharelado em Ciência da Computação -
 * UFSCar, Sorocaba
 *
 * Alunos: Nahim Alves de Souza RA 380059 Rafael Cláudio Domene RA 345040
 *
 * Professora: Yeda Regina Venturini
 *
 */
package nodes;

import rip.*;

public class node2 {

    rtpkt pktRotinaDois = new rtpkt();;
    tabelaDistancia distanciaDois = new tabelaDistancia();;
    int[] minCost = new int[4];

    public void rtInit2(RIP r) {
        //RIP r = new RIP();
        distanciaDois.setCusto(0, 0, 999);
        distanciaDois.setCusto(0, 1, 999);
        distanciaDois.setCusto(0, 2, 999);
        distanciaDois.setCusto(0, 3, 999);

        distanciaDois.setCusto(1, 1, 999);
        distanciaDois.setCusto(1, 2, 999);
        distanciaDois.setCusto(1, 0, 999);
        distanciaDois.setCusto(1, 3, 999);

        distanciaDois.setCusto(2, 0, 3);
        distanciaDois.setCusto(2, 1, 1);
        distanciaDois.setCusto(2, 2, 0);
        distanciaDois.setCusto(2, 3, 2);

        distanciaDois.setCusto(3, 1, 999);
        distanciaDois.setCusto(3, 2, 999);
        distanciaDois.setCusto(3, 0, 999);
        distanciaDois.setCusto(3, 3, 999);

        // Seta os caminhos de menor custo no cenario inicial
        minCost[0] = 3;
        minCost[1] = 1;
        minCost[2] = 0;
        minCost[3] = 2;

        // Seta os caminhos de menor custo no cenario inicial no pacote de rotina
        pktRotinaDois.setMinCost(0, minCost[0]);
        pktRotinaDois.setMinCost(1, minCost[1]);
        pktRotinaDois.setMinCost(2, minCost[2]);
        pktRotinaDois.setMinCost(3, minCost[3]);

        pktRotinaDois.setSourceID(2);

        // Envia seus caminhos de menor custo para os nós conectados
        // Para o nó 0
        pktRotinaDois.setDestID(0);
        r.toLayer2(pktRotinaDois);

        // Para o nó 1
        pktRotinaDois.setDestID(1);
        r.toLayer2(pktRotinaDois);

        // Para o nó 3
        pktRotinaDois.setDestID(3);
        r.toLayer2(pktRotinaDois);

        System.out.println("\nINIT NODE 2: ");
        this.printdt2(distanciaDois);
    }

    public void rtUpdate2(rtpkt rcvdpkt, RIP r) {
        
        int k;
        int auxCusto = 0;
        int vetAuxCusto[] = {0, 0, 0, 0};
        int mudanca = 0;
        //RIP r = new RIP();

        for (k = 0; k < 4; k++) {
            /* Se o custo de caminho do pacote de rotina recebido FOR MENOR
             * que o custo armazenado na tabela de distancia do nó dois para o nó o qual
             * enviou esse pacote( SourceID ), então a tabela de distancias do nó dois é atualizada
             * com o custo de caminho do pacote de rotina recebido
             */
            if (rcvdpkt.getMinCost(k) < distanciaDois.getCusto(rcvdpkt.getSourceID(), k)) {
                distanciaDois.setCusto(rcvdpkt.getSourceID(), k, rcvdpkt.getMinCost(k));
            }
        }

        /* Verificando o caminho de menor custo do nó dois para os demais nós
         * pois a tabela de distancias foi atualizada acima através do pacotes de
         * rotina recebido
         */

        // Verifica o menor caminho entre o nó 2 e nó 0
        auxCusto = Math.min(distanciaDois.getCusto(2, 0), distanciaDois.getCusto(2, 1) + distanciaDois.getCusto(1, 0));
        auxCusto = Math.min(auxCusto, distanciaDois.getCusto(2, 3) + distanciaDois.getCusto(3, 0));
        vetAuxCusto[1] = auxCusto;

        // Verifica o menor caminho entre o nó 2 e nó 1
        auxCusto = Math.min(distanciaDois.getCusto(2, 1), distanciaDois.getCusto(2, 0) + distanciaDois.getCusto(0, 1));
        auxCusto = Math.min(auxCusto, distanciaDois.getCusto(2, 3) + distanciaDois.getCusto(3, 0) + distanciaDois.getCusto(0, 1));
        vetAuxCusto[2] = auxCusto;

        // Verifica o menor caminho entre o nó 2 e nó 3
        auxCusto = Math.min(distanciaDois.getCusto(2, 3), distanciaDois.getCusto(2, 0) + distanciaDois.getCusto(0, 3));
        auxCusto = Math.min(auxCusto, distanciaDois.getCusto(2, 1) + distanciaDois.getCusto(1, 0) + distanciaDois.getCusto(0, 3));
        vetAuxCusto[3] = auxCusto;

        /* Verificamos se as distancias armazenadas no vetor vetAuxCusto são menores
         * que as atualmente armazenadas na tabela de distancias do nó dois
         */
        for (k = 0; k < 4; k++) {
            /* Se o custo de caminho armazenado no vetAuxCusto FOR MENOR
             * que o custo armazenado na tabela de distancia do nó dois, então
             * a tabela de distancias do nó dois é atualizada com o custo de
             * caminho armazenado em vetAuxCusto
             */
            if (vetAuxCusto[k] < distanciaDois.getCusto(2, k)) {
                distanciaDois.setCusto(2, k, rcvdpkt.getMinCost(k));
                mudanca = 1;
            }
        }


        // Se houve mudanca então envia um pacote de rotina para os nós adjacentes
        if (mudanca == 1) {
            // Para o nó 0
            pktRotinaDois.setDestID(0);
            r.toLayer2(pktRotinaDois);

            // Para o nó 1
            pktRotinaDois.setDestID(1);
            r.toLayer2(pktRotinaDois);

            // Para o nó 3
            pktRotinaDois.setDestID(3);
            r.toLayer2(pktRotinaDois);
        }
        
        System.out.println("\nUPDATE NODE 2: ");
        this.printdt2(distanciaDois);

    }

    public void printdt2(tabelaDistancia dtptr) {

        System.out.println("                via     ");
        System.out.println("   D2 |    0     1      3");
        System.out.println("  ----|------------------");
        System.out.println("     0|  " + dtptr.getCusto(0, 0) + "  " + dtptr.getCusto(0, 1) + "  " + dtptr.getCusto(0, 3));
        System.out.println("dest 1|  " + dtptr.getCusto(1, 0) + "  " + dtptr.getCusto(1, 1) + "  " + dtptr.getCusto(1, 3));
        System.out.println("     3|  " + dtptr.getCusto(3, 0) + "  " + dtptr.getCusto(3, 1) + "  " + dtptr.getCusto(3, 3));

    }

    public void linkHandler2(int destino, int novoCusto) {
        minCost[destino] = novoCusto;
    }
}
